package org.goldenport.g3.jetty

import javax.servlet.http.HttpServletRequest
import javax.servlet.http.HttpServletResponse
import javax.servlet.ServletException
import java.io.{File, IOException}
import org.eclipse.jetty.server._
import org.eclipse.jetty.server.handler._
import org.eclipse.jetty.servlet._
import org.eclipse.jetty.http.MimeTypes
import com.asamioffice.goldenport.servlet.StubServletContext
import org.goldenport.g3.{G3Context, G3Application}
import org.goldenport.g3.servlet.G3Servlet

/**
 * @since   May.  4, 2010
 * @version Jun. 22, 2011
 * @author  ASAMI, Tomoharu
 */
class JettyServer(val context: G3Context, anApp: Option[G3Application]) extends AbstractHandler {
  private lazy val g3_servlet = new G3Servlet(anApp)
  private lazy val _servlet_context = JettyServer.servletContext(context)

  override def doStart() {
    println("JettyServer = " + _servlet_context)
    g3_servlet.init(_servlet_context)
  }

  override def doStop() {
    g3_servlet.destroy()
  }

  def handle(target: String,
             baseRequest: Request,
             request: HttpServletRequest,
             response: HttpServletResponse) {
    context.logInfo(this, request.getPathInfo())
    baseRequest.setHandled(true)
    g3_servlet.service(request, response)
  }
}

object JettyServer {
  def servletContext(context: G3Context) = {
    val sc = new StubServletContext()
    for (param <- context.getParameter("g3.application")) {
      sc.setInitParameter("g3.application", param.toString)
    }
    for (param <- context.getParameter("g3.datastore")) {
      sc.setInitParameter("g3.datastore", param.toString)
    }
    for (param <- context.getParameter("g3.http.format")) {
      sc.setInitParameter("g3.http.format", param.toString)
    }
    sc
  }

  def start(context: G3Context, anApp: Option[G3Application]) {
    val mime = new MimeTypes
    mime.addMimeMapping("atom", "application/atom+xml")
    mime.addMimeMapping("atomsvc", "application/atomsvc+xml")
    mime.addMimeMapping("atomcat", "application/atomcat+xml")
    mime.addMimeMapping("manifest", "text/cache-manifest")
    mime.addMimeMapping("eventstream", "text/event-stream")
    
    def resource_html = new ResourceHandler {
      val url = getClass.getClassLoader.getResource("html")
      if (url != null) {
        setResourceBase(url.toExternalForm)
      }
      setMimeTypes(mime)
    }

    def resource_webinf = new ResourceHandler {
      val url = getClass.getClassLoader.getResource("WEB-INF")
      if (url != null) {
        setResourceBase(url.toExternalForm)
      }
      setMimeTypes(mime)
    }

    def file_html = new ResourceHandler {
      val url = new File("html").toURI.toURL
      if (url != null) {
        setResourceBase(url.toExternalForm)
      }
      setMimeTypes(mime)
    }

    def websocket_servlet = new ServletContextHandler {
      val serv = new JettyWebSocketServlet(anApp)
      serv.init(servletContext(context))
      addServlet(new ServletHolder(serv), "/ws/*")
    }

    def server_port = context.getParameterInt("g3.server.port", 8765)

    val server = new Server(server_port)
    val handlers = new HandlerList
    handlers.addHandler(resource_html)
    handlers.addHandler(resource_webinf)
    handlers.addHandler(file_html)
    handlers.addHandler(websocket_servlet)
    handlers.addHandler(new JettyServer(context, anApp))
    server.setHandler(handlers)
    server.start()
    server.join()
  }
}
